#ifndef __CURVE_H__
#define __CURVE_H__

#include "glm/glm.hpp"

#if _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif

namespace RayFrame
{
  class DLL_DECLARE Curve
  {
  public:
    typedef std::vector<glm::vec2> PointList;
    typedef PointList::iterator    IterPointList;
    enum CurveType
    {
      LINEAR,
    };

    Curve()
    {
      m_type = LINEAR;
    };

    bool SetKeys(float *keyX, float *keyY, int keyCount, CurveType type)
    {
      for(int i=0; i<keyCount; i++)
      {
        assert(i+1 >= keyCount || keyX[i] < keyX[i+1]);
        if(i+1 < keyCount &&  keyX[i] > keyX[i+1])
        {
          LOG_ERROR1("Invalid interpolate data.");
          return false;
        }

        m_keys.push_back(glm::vec2(keyX[i], keyY[i]));
      }
      m_type = type;
      return true;
    }

    bool SetKeys(PointList keys, CurveType type)
    {
      if(keys.empty())
        return false;

      m_keys = keys;
      m_type = type;
      return true;
    }

    float GetValue(float x)
    {
      for(IterPointList iter = m_keys.begin();
        iter+1 != m_keys.end(); iter++ )
      {
        if(x > (iter+1)->x)
          continue;

        glm::vec2 &crtKey = (*iter);
        glm::vec2 &nextKey = *(iter+1);

        float ratio = (x-crtKey.x) / (nextKey.x - crtKey.x);
        return crtKey.y * (1.0f - ratio) + nextKey.y * (ratio);
      }

      return m_keys.back().y;
    }

    float GetValue(float x, float defaultValue)
    {
      if(m_keys.empty())
        return defaultValue;
      else
        return GetValue(x);
    }
  protected:
    PointList m_keys;
    CurveType m_type;
  };
};

#if _MSC_VER
#pragma warning(pop)
#endif //_MSC_VER

#endif // __CURVE_H__
